#pragma once
#include "Sound.h"

Sound::Sound()
{
	SoundChannel = NULL;
	ChannelVolume = NULL;
	ChannelPan = NULL;
	numberOfSound = NULL;
	sizeSound = NULL;
}

Sound::~Sound()
{
	shutdownDirectSound();
}

LPDIRECTSOUNDBUFFER Sound::LoadWaveToSoundBuffer(std::string wavFilename)
{
	LPDIRECTSOUNDBUFFER apDSBuffer = NULL;
	CWaveFile *wavFile;
	HRESULT hr;

	wavFile = new CWaveFile();
	wavFile->Open((char*)wavFilename.c_str(), NULL, WAVEFILE_READ );
	if( wavFile->GetSize() == 0 )
	{
		MessageBox(*wndHandle, "invalid file", "ERROR", MB_OK);
		return false;
	}

	DSBUFFERDESC dsbd;
	ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
	dsbd.dwSize          = sizeof(DSBUFFERDESC);
	dsbd.dwFlags         = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN;
	dsbd.dwBufferBytes   = wavFile->GetSize();
	dsbd.guid3DAlgorithm = GUID_NULL;
	dsbd.lpwfxFormat     = wavFile->m_pwfx;

	hr = g_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer, NULL );
	if FAILED (hr)
	{
		MessageBox(NULL, "unable to create sound buffer", "ERROR", MB_OK);
		return NULL;
	}

	VOID*   pDSLockedBuffer      = NULL; // Pointer to locked buffer memory
	DWORD   dwDSLockedBufferSize = 0;    // Size of the locked DirectSound buffer
	DWORD   dwWavDataRead        = 0;    // Amount of data read from the wav file 
		
	hr = apDSBuffer->Lock( 0, wavFile->GetSize(), 
							&pDSLockedBuffer, &dwDSLockedBufferSize, 
							NULL, NULL, 0L );
	if FAILED (hr)
		return NULL;

	// Reset the wave file to the beginning 
	wavFile->ResetFile();

	// Read the wave file
	hr = wavFile->Read( (BYTE*) pDSLockedBuffer,
						dwDSLockedBufferSize, 
						&dwWavDataRead );
	// Check to make sure that this was successful
	if FAILED (hr)
		return NULL;

	// Check to make sure the wav file is not empty
	if( dwWavDataRead == 0 )
	{
		// Wav is blank, so just fill with silence
		FillMemory( (BYTE*) pDSLockedBuffer, 
					dwDSLockedBufferSize, 
					(BYTE)(wavFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
	}
	else if( dwWavDataRead < dwDSLockedBufferSize )
	{
		// Don't repeat the wav file, just fill in silence 
		FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, 
					dwDSLockedBufferSize - dwWavDataRead, 
					(BYTE)(wavFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
	}

	// Unlock the buffer, we don't need it anymore.
	apDSBuffer->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );

	// Clean up
	delete wavFile;

	return apDSBuffer;
}
bool Sound::playSound(int bufferID)
{
	if(bufferID < 0 || bufferID >=  getSize()) 
	{
		MessageBox(NULL, "BufferID in playSound does not exist", "Sound ERROR!", MB_OK);
		return false;
	}

	if(SoundChannel[bufferID])
		SoundChannel[bufferID]->Play( 0, 0, 0);

	return true;
}

bool Sound::playSoundLoop(int bufferID)
{
	if(bufferID < 0 || bufferID >=  getSize()) 
	{
		MessageBox(NULL, "BufferID in playSoundLoop does not exist", "Sound ERROR!", MB_OK);
		return false;
	}

	if(SoundChannel[bufferID])
		SoundChannel[bufferID]->Play( 0, 0, DSBPLAY_LOOPING );

	return true;
}

bool Sound::stopSound(int bufferID)
{
	if(bufferID < 0 || bufferID >=  getSize())
	{
		MessageBox(NULL, "BufferID in stopSound does not exist", "Sound ERROR!", MB_OK);
		return false;
	}

	if(SoundChannel[bufferID])
	{
		SoundChannel[bufferID]->Stop();
		SoundChannel[bufferID]->SetCurrentPosition(0);
	}
	return true;
}

bool Sound::initDirectSound(HWND hwnd)
{
	HRESULT hr;

	hr = DirectSoundCreate8( NULL, &g_pDS, NULL );
	if FAILED (hr)
		return false;

	// Set DirectSound cooperative level 
	hr = g_pDS->SetCooperativeLevel( hwnd, DSSCL_PRIORITY );
	if FAILED ( hr )
		return false;

	return true;
}
bool Sound::LoadSound(std::string wavFilename)
{
	//if(bufferID < 0) return false;
	
	int bufferID = 0;

	std::ifstream textFile;

	textFile.open(wavFilename.c_str());
	while(!textFile.eof())
	{
		textFile >> wavFilename;
		SoundChannel[bufferID] = LoadWaveToSoundBuffer(wavFilename);
		bufferID++;
	}
	textFile.close();

	return true;	
}
int Sound::countFiles(std::string wavFilename)
{
	int i_fileNum = 0;	
	std::ifstream textFile;

	textFile.open(wavFilename.c_str());
	while(!textFile.eof())
	{
		textFile >> wavFilename;
		i_fileNum++;
	}
	textFile.close();
	sizeSound = i_fileNum;
	return i_fileNum;	
}
void Sound::initSoundFiles(std::string wavFilename, HWND hwnd)
{
	countFiles(wavFilename);
	initDirectSound(hwnd);

	SoundChannel = new LPDIRECTSOUNDBUFFER[getSize()];// number of buffers that will be use

	//loading sound file
	for(int bufferID = 0; bufferID < getSize(); bufferID++)
	{
		SoundChannel[bufferID] = NULL;	// all buffers are set back to NULL
	}

	LoadSound(wavFilename);
}

void Sound::shutdownDirectSound(void)
{
	// realease all sound buffers
	for(int bufferID = 0; bufferID < getSize(); bufferID++)
	{
		SoundChannel[bufferID]->Stop();
		SoundChannel[bufferID]->Release();
	}
	
	// release direct sound
	//if (g_pDS)
	{
		g_pDS->Release();
		g_pDS = NULL;
	}

	// always check to see if you need to call delete before just deleting
	// added the if statements to fix a runtime error - Michael Alstad

	if(SoundChannel)
		delete [] SoundChannel; // delete channels
	if(ChannelVolume)
		delete [] ChannelVolume; // delete all volume variables
	if(ChannelPan)
	delete [] ChannelPan; // delete all pan vairables
}
void Sound::ChangeVolume(int volume, int bufferID)
{
	if(bufferID < 0 || bufferID >=  getSize())
	{
		MessageBox(NULL, "BufferID in Volume does not exsit", "Sound ERROR!", MB_OK);
	}

	if(SoundChannel[bufferID])
		SoundChannel[bufferID]->SetVolume(volume);
}
void Sound::ChangePan(int pan, int bufferID)
{
	if(bufferID < 0 || bufferID >= getSize())
	{
		MessageBox(NULL, "BufferID in Pan does not exist", "Sound ERROR!",MB_OK);
		return; 
	}
	if(SoundChannel[bufferID])
		SoundChannel[bufferID]->SetPan(pan);
}
int Sound::getSize()
{
	return sizeSound;
}